#include "uhm.hxx"

#define N 1

using namespace uhm;

typedef ID_Node_H_<N>          Id_Nd;
typedef ID_Element_<N>         Id_El;
typedef LU_nopiv_Linal_        Uhm;

typedef Solver_<Id_Nd,Id_El,Uhm> Solver;

int main (int argc, char **argv) {

  initialize(argc, argv);

  // ** Environments
  Int_
    type = Mat_Base_::FLOAT,
    uplo = Mat_Base_::FULL,
    sym  = Mat_Base_::SYM,
    rhs  = 1,
    blk  = 256;

  Int_
    kind = Mesh_Base_::NODE_DEFAULT;

  // ** Time measuring begin
  time_begin();

  // ** Solver initialization
  Solver solver(type, uplo, sym, rhs, blk);

  // ** Import a mesh from a file_in
  option_begin();
  std::string fin;
  get_option_string("-in", "Reading a file", __FILE__,
                    "../../../uhmfile/toy_1.uhm", fin);
  option_end();

  std::cout << "Opening file ... " << fin << std::endl;
  std::ifstream in;
  in.open(fin.c_str());
  stream2mesh<Solver::_Mesh_>(in, solver.mesh());
  in.close();

  // ** Create random matrices in work
  UHM_ERROR((mesh2cache<Solver::_Mesh_,Solver::_Cache_>(solver.mesh(), solver.work())),
            ">> Error in mesh2cache");
  
  time_in("tree:: Solver Creating");

  // ** Create tree
  time_in("tree:: Mesh2Tree");
  UHM_ERROR((mesh2tree<Solver::_Mesh_,Solver::_Tree_>(solver.mesh(),solver.tree())),
            ">> Error in mesh2tree");
  time_out();

  // ** Separating nodes
  time_in("tree:: Separating Nodes");
  UHM_ERROR((op_leaf_to_me_par<Solver::_Tree_>(solver.tree().get_root(), 
                                               &op_elt_separate_nodes<Solver::_Tree_>)),
            ">> Error in Separating Nodes");
  time_out();
  
  time_out();

  Int_ max_dof, min_dof, total_dof;
  total_dof = solver.mesh().get_dof(max_dof, min_dof);
  
  std::cout << "Total Dof = " << total_dof << ", Max UHM = " << max_dof << ", Min UHM = " << min_dof << std::endl;

  UHM_ERROR(solver.clear(), ">> Error in Solver Clearing");
  UHM_ERROR(solver.flush(), ">> Error in Solver Flushing");

  time_end();

  finalize();

  return true;
}


